/* * Sun Public License Notice * * The contents of this file are subject to the Sun Public License * Version 1.0 (the "License"). You may not use this file except in * compliance with the License. A copy of the License is available at * http://www.sun.com/ * * The Original Code is Forte for Java, Community Edition. The Initial * Developer of the Original Code is Sun Microsystems, Inc. Portions * Copyright 1997-2000 Sun Microsystems, Inc. All Rights Reserved. */ package org.netbeans.core; import java.awt.*; import java.awt.datatransfer.Clipboard; import java.awt.event.*; import java.beans.*; import java.lang.ref.SoftReference; import java.io.*; import java.net.URL; import java.util.Enumeration; import java.util.Vector; import javax.swing.JComponent; import javax.swing.JFrame; import javax.swing.JPanel; import javax.swing.UIManager; import javax.swing.border.*; import org.openide.util.datatransfer.ExClipboard; import org.openide.*; import org.openide.loaders.*; import org.openide.filesystems.*; import org.openide.options.ControlPanel; import org.openide.windows.*; import org.openide.explorer.*; import org.netbeans.core.actions.*; import org.openide.util.HelpCtx; import org.openide.util.WeakListener; import org.openide.util.NbBundle; import org.openide.util.RequestProcessor; import org.openide.util.UserCancelException; import org.openide.util.actions.ActionPerformer; import org.openide.util.actions.SystemAction; import org.openide.util.io.*; import org.openide.nodes.*; import org.openide.nodes.Children; import org.openide.windows.TopComponent; import org.netbeans.core.windows.WorkspaceImpl; import org.netbeans.core.windows.WindowManagerImpl; import org.netbeans.core.windows.ModeImpl; /** Class that provides operations on nodes. Any part of system can * ask for opening a customizer or explorer on any node. These actions * are accessible thru this class. */ public class NbNodeOperation extends TopManager.NodeOperation { /** default explorer class */ private static final String EXPLORER_NAME = "org.netbeans.core.NbMainExplorer$ExplorerTab"; // NOI18N /** name of class for to work as explorer */ private static String explorerName; /** default properties class */ private static final String PROPERTIES_NAME = "org.netbeans.core.NbNodeOperation$Sheet"; // NOI18N /** name of class for to work as property displayer */ private static String propertiesName; /** Shows an explorer on the given root Node. * @param n the Node that will be the rootContext of the explored hierarchy */ public void explore (Node n) { try { Object o = createObject (explorerName, EXPLORER_NAME); ExplorerManager.Provider p = (ExplorerManager.Provider)o; p.getExplorerManager ().setRootContext (n); TopComponent c = (TopComponent)o; c.open (); } catch (ClassCastException ex) { TopManager.getDefault ().notifyException (ex); } } /** Tries to open customization for specified node. The dialog is * open in modal mode and the function returns after successful * customization. * * @param n the node to customize * @return <CODE>true</CODE> if the node has customizer, * <CODE>false</CODE> if not */ public boolean customize (Node n) { java.awt.Component customizer = n.getCustomizer (); if (customizer == null ) return false; if (customizer instanceof java.awt.Window) { ((java.awt.Window)customizer).pack (); customizer.setVisible (true); return true; } Dialog dialog = new org.openide.explorer.propertysheet.PropertyDialogManager ( //TopManager.getDefault ().getMainWindow (), NbBundle.getBundle (NbNodeOperation.class).getString ("CTL_Customizer_dialog_title"), customizer, true).getDialog(); dialog.pack(); dialog.show(); return true; } /** Opens a modal propertySheet on given Node * @param n the node to show properties for */ public void showProperties (Node n) { try { Object o = createObject (propertiesName, PROPERTIES_NAME); ExplorerManager.Provider p = (ExplorerManager.Provider)o; p.getExplorerManager ().setRootContext (n); p.getExplorerManager ().setSelectedNodes (new Node[] { n }); openProperties((TopComponent)o); } catch (Exception ex) { TopManager.getDefault ().notifyException (ex); } } /** Opens a modal propertySheet on given set of Nodes * @param n the array of nodes to show properties for */ public void showProperties (Node[] nodes) { try { Object o = createObject (propertiesName, PROPERTIES_NAME); ExplorerManager.Provider p = (ExplorerManager.Provider)o; ExplorerManager m = p.getExplorerManager (); if (nodes.length == 0) { m.setRootContext (new AbstractNode (Children.LEAF)); } else { m.setRootContext (NodeOp.findRoot (nodes[0])); m.setSelectedNodes (nodes); } openProperties((TopComponent)o); } catch (Exception ex) { TopManager.getDefault ().notifyException (ex); } } /** Opens explorer for specified root in modal mode. The set * of selected components is returned as a result. The acceptor * should be asked each time selected nodes changes to accept or * reject the current result. This should affect for example the * <EM>OK</EM> button. * * @param title is a title that will be displayed as a title of the window * @param root the root to explore * @param acceptor the class that is asked for accepting or rejecting * current selection * @param top is a component that will be displayed on the top * @return array of selected (and accepted) nodes * * @exception UserCancelException selection interrupted by user */ public Node[] select (String title, String rootTitle, Node root, NodeAcceptor acceptor, Component top) throws org.openide.util.UserCancelException { FileSelector selector = new FileSelector (title, rootTitle, root, acceptor, top); selector.show(); if (selector.cancelFlag) throw new org.openide.util.UserCancelException (); return selector.getNodes (); } /** Helper method, opens properties top component in single mode * and requests a focus for it */ private void openProperties (TopComponent tc) { WindowManagerImpl wm = (WindowManagerImpl)TopManager.getDefault().getWindowManager(); WorkspaceImpl curWorkspace = (WorkspaceImpl)wm.getCurrentWorkspace(); String modeName = wm.findUnusedModeName(tc.getName(), curWorkspace); curWorkspace.createMode( modeName, modeName, null, ModeImpl.SINGLE, true ).dockInto(tc); tc.open(); tc.requestFocus(); } /** Creates instance of class either from first name or * if it fails from the second, surely valid name. * @param n1 first name to try (or null) * @param n2 second name * @return the created object */ private static Object createObject (String n1, String n2) { TopManager top = TopManager.getDefault (); if (n1 != null) { // try this name try { Object o = Beans.instantiate (top.currentClassLoader (), n1); return o; } catch (Exception e) { top.notifyException (e); } // never mind, try default } try { Object o = Beans.instantiate (top.currentClassLoader (), n2); return o; } catch (Exception e) { throw new InternalError (); } } /** Default view for properties. */ public static class Sheet extends ExplorerPanel { /** generated Serialized Version UID */ static final long serialVersionUID = 7807519514644165460L; /** shared sheet */ private static Sheet sharedSheet; /** The SheetFrame's icon SoftReference (Image) */ private static SoftReference sheetIcon; /** listener to the property changes */ transient private Listener listener; /** Should property sheet listen to the global changes ? */ boolean global; /** Constructor for new sheet. * The sheet does not listen to global changes */ public Sheet () { // PENDING this probably should be false, // this is only for testing purposes this (false); } /** @param global should the content change when global properties changes? */ public Sheet (boolean global) { this.global = global; add ("Center", new org.openide.explorer.propertysheet.PropertySheetView ()); // NOI18N initIcon (); // name listener listener = new Listener (); getExplorerManager ().addPropertyChangeListener (listener); updateGlobalListening(true); } /** Provides the shared instance of SheetFrame */ public static Sheet getDefault () { if (sharedSheet == null) sharedSheet = new Sheet (true); return sharedSheet; } public HelpCtx getHelpCtx () { return getHelpCtx (getExplorerManager ().getSelectedNodes (), new HelpCtx (Sheet.class)); } /** Provides the icon to be shown as this Window's icon. * @return the window's icon */ private void initIcon () { Image icon = sheetIcon == null ? null : (Image)sheetIcon.get (); if (icon == null) { icon = java.awt.Toolkit.getDefaultToolkit ().getImage ( getClass ().getResource ( org.openide.util.Utilities.isLargeFrameIcons() ? "/org/netbeans/core/resources/frames/properties32.gif" : // NOI18N "/org/netbeans/core/resources/frames/properties.gif" // NOI18N ) ); sheetIcon = new SoftReference (icon); } setIcon (icon); } /** Changes name of the component to reflect currently displayed nodes. * Called when set of displayed nodes has changed. */ protected void updateTitle () { Node[] nodes = getExplorerManager ().getSelectedNodes (); // different naming for global and local sheets if (global) { setName( java.text.MessageFormat.format( NbBundle.getBundle(NbNodeOperation.class).getString("CTL_FMT_GlobalProperties"), new Object[] { new Integer (nodes.length), nodes.length == 0 ? "" : nodes[0].getDisplayName() // NOI18N } ) ); } else { setName( java.text.MessageFormat.format( NbBundle.getBundle(NbNodeOperation.class).getString("CTL_FMT_LocalProperties"), new Object[] { new Integer (nodes.length), nodes.length == 0 ? "" : nodes[0].getDisplayName() // NOI18N } ) ); } } /** Reshapes the window so that is is sized according to its preferredSize * and places it into the center of the screen * public void center() { // standard way how to place the dialog to the center of the screen pack(); Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize(); Dimension dialogSize = getSize(); setLocation((screenSize.width-dialogSize.width)/2,(screenSize.height-dialogSize.height)/2); }*/ public Dimension getPreferredSize () { return new Dimension (250, 400); } /** Serialize this property sheet */ public void writeExternal (ObjectOutput out) throws IOException { super.writeExternal(out); out.writeObject(new Boolean(global)); } /** Deserialize this property sheet. */ public void readExternal (ObjectInput in) throws IOException, ClassNotFoundException { super.readExternal(in); global = ((Boolean)in.readObject()).booleanValue(); // start global listening if needed, but wait until // deserialization is done (ExplorerManager is uses // post-deserialization validating too, so we are forced // to use it) ((ObjectInputStream)in).registerValidation( new ObjectInputValidation () { public void validateObject () { updateGlobalListening(false); } }, 0 ); } /** Resolve to singleton instance, if needed. */ public Object readResolve () throws ObjectStreamException { return global ? getDefault() : this; } /** Helper, listener variable must be initialized before * calling this */ private void updateGlobalListening (boolean activateNow) { if (global) { TopComponent.getRegistry().addPropertyChangeListener( WeakListener.propertyChange(listener, TopComponent.getRegistry ()) ); if (activateNow) listener.activate (); } } /** Change listener to changes in selected nodes. And also * nodes listener to listen to global changes of the nodes. */ private class Listener extends Object implements PropertyChangeListener { public void propertyChange (PropertyChangeEvent ev) { if (ev.getPropertyName ().equals (ExplorerManager.PROP_SELECTED_NODES)) { //updateTitle(); } else if (ev.getPropertyName ().equals (TopComponent.Registry.PROP_ACTIVATED_NODES)) { try { ExplorerManager man = getExplorerManager (); Node[] arr = (Node[]) ev.getNewValue(); if (arr.length > 0) { man.setRootContext (NodeOp.findRoot (arr[0])); } man.setSelectedNodes (arr); updateTitle(); } catch (PropertyVetoException e) { // ignore it } } } public void activate () { try { ExplorerManager man = getExplorerManager (); Node[] arr = TopComponent.getRegistry ().getActivatedNodes(); if (arr.length > 0) { man.setRootContext (NodeOp.findRoot (arr[0])); } man.setSelectedNodes (arr); } catch (PropertyVetoException e) { // ignore it } } } } } /* * Log * 37 Gandalf 1.36 1/13/00 Jaroslav Tulach I18N * 36 Gandalf 1.35 1/7/00 David Simonek global and local * property sheets now have different titles * 35 Gandalf 1.34 12/21/99 David Simonek shared property sheet * behaves like real singleton after deserialization * 34 Gandalf 1.33 12/17/99 David Simonek #4861 * 33 Gandalf 1.32 12/6/99 David Simonek explore() method updated * (toolbar removed from the view) * 32 Gandalf 1.31 11/5/99 Jesse Glick Context help jumbo * patch. * 31 Gandalf 1.30 11/5/99 Jaroslav Tulach WeakListener has now * registration methods. * 30 Gandalf 1.29 11/3/99 David Simonek name change bugfix * 29 Gandalf 1.28 10/22/99 Ian Formanek NO SEMANTIC CHANGE - Sun * Microsystems Copyright in File Comment * 28 Gandalf 1.27 8/9/99 David Simonek request focus added to * showProperties * 27 Gandalf 1.26 8/1/99 David Simonek * 26 Gandalf 1.25 7/28/99 David Simonek workspace serialization * bugfixes * 25 Gandalf 1.24 7/11/99 David Simonek window system change... * 24 Gandalf 1.23 7/2/99 Jesse Glick Bugfix--now uses * ExplorerPanel's HelpCtx. * 23 Gandalf 1.22 6/24/99 Jesse Glick Gosh-honest HelpID's. * 22 Gandalf 1.21 6/22/99 Ian Formanek employed DEFAULT_HELP * 21 Gandalf 1.20 6/8/99 Ian Formanek ---- Package Change To * org.openide ---- * 20 Gandalf 1.19 4/2/99 Jaroslav Tulach global properites. * 19 Gandalf 1.18 3/29/99 Ian Formanek Removed obsoleted * imports of ButtonBar * 18 Gandalf 1.17 3/26/99 Jaroslav Tulach * 17 Gandalf 1.16 3/26/99 Jaroslav Tulach * 16 Gandalf 1.15 3/26/99 Ian Formanek Fixed use of obsoleted * NbBundle.getBundle (this) * 15 Gandalf 1.14 3/18/99 Ian Formanek Removed obsoleted import * 14 Gandalf 1.13 3/18/99 David Simonek modes... * 13 Gandalf 1.12 3/9/99 Jaroslav Tulach ButtonBar * 12 Gandalf 1.11 3/9/99 Ian Formanek Reflecting ExplorerPanel * using BorderLayout by default * 11 Gandalf 1.10 2/27/99 Jaroslav Tulach Shortcut changed to * Keymap * 10 Gandalf 1.9 2/17/99 David Simonek setRequestedSize method * added to the window system getDefaultMode added to the TopComponent * 9 Gandalf 1.8 2/12/99 Ian Formanek Reflected renaming * Desktop -> Workspace * 8 Gandalf 1.7 2/8/99 Jaroslav Tulach Pernamently updatable * properties * 7 Gandalf 1.6 2/5/99 Jaroslav Tulach * 6 Gandalf 1.5 2/4/99 Jaroslav Tulach Properties and explorer * 5 Gandalf 1.4 1/20/99 Petr Hamernik * 4 Gandalf 1.3 1/7/99 Ian Formanek fixed resource names * 3 Gandalf 1.2 1/6/99 Ian Formanek Reflecting changes in * location of package "awt" * 2 Gandalf 1.1 1/6/99 Jaroslav Tulach ide.* extended to * ide.loaders.* * 1 Gandalf 1.0 1/5/99 Ian Formanek * $ */